//#define F_CPU 1000000L define by ECLIPSE
#include <avr/io.h>
#include <avr/interrupt.h> //dołączenie biblioteki z przerwaniami
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <Consts.h>
#include <DarkDefines.h>
#include <USART.h>
#include "IOCfg.h"
#include "PWM.h"
#include <Communication.h>
#include "StatusLed.h"

/* GLOBALS */

unsigned char LAMPS[2] = {0};
void LAMP_setState(unsigned char id, bool on) {

	if(on != FALSE)
	{
		PORTC |= _BV(LAMPS[id]);
	}
	else
	{
		PORTC &= ~_BV(LAMPS[id]);
	}
}

bool validation(unsigned char data) {
	static char first = 0;

	if (first == ~data) {
		return TRUE;
	}

	if (first) {
		first = 0;
	} else {
		first = data;
	}

	return FALSE;
}
int main(void) {

	bool stateChanged = FALSE;
	unsigned int i = 0; // increment for PWM

	PWM_Init(i);
	USART1_Init();
	bool pwmOn = TRUE;

// Button states - [FUTDEV]	Remove!
	bool pressedInc = FALSE; // flag for checking if button was pressed
	bool pressedDec = FALSE; // flag for checking if button was pressed

// notify that initialization is finished
	StatusLed_blink(ST_INFO, LED_BLUE);
	StatusLed_blink(ST_INFO, LED_GREEN);

	//main dispatching loop
	while (1) {
		if (UCSRA & _BV(RXC)) {
			StatusLed_blink(ST_INFO, LED_BLUE);
			StatusLed_blink(ST_INFO, LED_GREEN);
		}

		if (!(PIND & _BV(PD6))) {
			while (!(PIND & _BV(PD6))) {
			}
			//PWM TOGGLING
			if (!pwmOn) {
				StatusLed_blink(ST_INFO, LED_BLUE);
				stateChanged = TRUE;
				//pwmOff = FALSE;
				pwmOn = PWM_changeState(TRUE);
				//Led management
				PORTB |= _BV(PB2);
				PORTC |= _BV(PC5);

			} else {
				StatusLed_blink(ST_INFO, LED_BLUE);

				pwmOn = PWM_changeState(FALSE);
				//Led manageent
				PORTC &= ~_BV(PC5);
				PORTB &= ~_BV(PB2);
			}
			_delay_ms(100);

		}

		if (pwmOn && !(PINB & _BV(PB0))) {
			if (0 < i && pressedDec != TRUE) // <= i - just to ensure
			{
				stateChanged = TRUE;
				PWM_manage(FALSE);
			} else {
				StatusLed_blink(ST_ERROR, LED_BLUE);
			}

			pressedDec = TRUE;
		} else {
			pressedDec = FALSE;
		}

		if (pwmOn && !(PIND & _BV(PD7))) {
			if ( MAX > i && pressedInc != TRUE) {
				stateChanged = TRUE;
				PWM_manage(TRUE);
			} else {
				StatusLed_blink(ST_ERROR, LED_BLUE);
			}
			pressedInc = TRUE;
		} else {
			pressedInc = FALSE;
		}
		if (!pwmOn && stateChanged) {
			if (0 >= i) {
				PWM_setValue(0x0);
				PWM_changeState(FALSE);
				PORTB &= ~_BV(PB1);

			} else if (MAX <= i) {
				PWM_setValue(MAX);
				PWM_changeState(FALSE);
				PORTB |= _BV(PB1);
			} else {
				if (!PWM_getState()) {
					PWM_changeState(TRUE);
				}
				PWM_setValue(i);
			}
			stateChanged = FALSE;
		}
	}
}

ISR(INT0_vect) {
	_delay_ms(1);
	if ((PIND & _BV(PD2))) //A HIGH
	{

		if (!(PIND & _BV(PD4)))
			PWM_manage(TRUE); //B LOW
		else
			PWM_manage(FALSE); // B HIGH

	} else //A LOW
	{
		//B LOW					              // B HIGH
		!(PIND & _BV(PD4)) ? PWM_manage(FALSE) : PWM_manage(TRUE);
	}
	GIFR |= _BV(INTF0);
}

ISR (USART_RXC_vect) {
	//echo implementation
	volatile unsigned char data = UDR;

	validation(data);
//	UDR = c;
//	while(!(UCSRA & _BV(TXC)) );
//	UDR = '\r';
//	while(!(UCSRA & _BV(TXC)) );
//	UDR = '\n';
//	while(!(UCSRA & _BV(TXC)) );
	//0x0000000x
	if (data & POS_led) {
		//0xXXXXX000
		volatile unsigned char value = (data >> POS_value);
		PWM_setValue(value);
	} else if (data & POS_lamp1) {
		LAMP_setState(POS_lamp1, data & _BV(POS_value));
	} else if (data & POS_lamp2) {
		LAMP_setState(POS_lamp2, data & _BV(POS_value));
	} else {
		StatusLed_blink(ST_ERROR, LED_GREEN);
	}



}

